/**
 * Copyright ©2016-2020 northkingbpo Corporation, All Rights Reserved
 * http://www.northkingbpo.net/
 */
package profile.hujia.simulation.data.service;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import profile.hujia.simulation.data.common.CommonFunction;
import profile.hujia.simulation.data.config.SystemConfig;
import profile.hujia.simulation.data.domain.*;

import java.util.*;

/**
 * class info
 *
 * @author hujia
 * @date 2019-06-11 10:52
 */
@Slf4j
@Data
public class GeneratePerson {

    private Integer numberOfPerson;
    private Integer numberOfBusinessType;
    private String[] singleNames;
    private String[] singleBusinessNames;
    private HashMap<Integer, Person> persons;
    //    private HashMap<Integer, List<Integer>> statistic;
//    private HashMap<Integer, List<Integer>> statisticAfter;
    private SingleLabelArg singleLabelArg;
    private SingleBusinessLabelArg singleBusinessLabelArg;
    private BusinessQueue businessQueue;
//    private HashMap<Integer, HashMap<String, Integer>> cache;


    public GeneratePerson(BusinessQueue businessQueue, SingleLabelArg singleLabelArg,
                          SingleBusinessLabelArg singleBusinessLabelArg) {
        this.singleNames = SystemConfig.SINGLE_NAME;
        this.singleBusinessNames = SystemConfig.SINGLE_BUSINESS_NAME;
        this.numberOfPerson = SystemConfig.TOTAL_PERSON_NUMBER;
        this.numberOfBusinessType = SystemConfig.TOTAL_BUSINESS_TYPE;
        persons = new HashMap<>();
        for (int i = 0; i < numberOfPerson; ++i) {
            persons.put(i + 1, new Person(i + 1));
        }
        this.singleLabelArg = singleLabelArg;
        this.singleBusinessLabelArg = singleBusinessLabelArg;
        this.businessQueue = businessQueue;
    }

    public void run() {
        createSingleLabelAttribute();
        createSingleBusinessLabelAttribute();
    }

    private void createSingleBusinessLabelAttribute() {
        createSpecificBusiness();
        createEachBusinessLabel();
    }

    private void createSpecificBusiness() {
        //view every people
        for (int i = 0; i < numberOfPerson; ++i) {
            //get the number of business
            Integer businessCount = persons.get(i + 1).getLabelMap().get("BusinessCount");
//            if (businessCount >= 50) {
//                log.info("error");
//            }
            //create specific business
            List<Integer> businessNumbers = CommonFunction.createUniqueRandomValues(businessCount, 1,
                    numberOfBusinessType);
            //statistic the business to queue
            for (int j = 0; j < businessCount; ++j) {
                businessQueue.statisticBusiness(businessNumbers.get(j), i + 1);
                persons.get(i + 1).getBusinessAttribute().put(businessNumbers.get(j), new Business(businessNumbers.get(j)));
            }
        }
    }

    private void createEachBusinessLabel() {
        Random random = new Random();
        //business
        for (int k = 0; k < numberOfBusinessType; ++k) {
            List<Integer> queue = businessQueue.getQueue(k + 1);
            Integer businessTotal = businessQueue.getQueueLength(k + 1);
            //which attribute
            for (int i = 0; i < singleBusinessNames.length; ++i) {
                String labelName = singleBusinessNames[i];
                List<Double> ratioList = singleBusinessLabelArg.getRatioMap().get(labelName);
                List<NumberRange> rangeList = singleBusinessLabelArg.getRangeMap().get(labelName);
                List<String> labelList = singleBusinessLabelArg.getLevelMap().get(labelName);


                List<Integer> values = CommonFunction.createUniqueRandomValues(businessTotal, 0, businessTotal - 1);
                Integer tmpSum = 0;
                Integer begin = 0;
                //which level
                for (int j = 0; j < rangeList.size(); ++j) {
                    //convert to integer
                    NumberRange tmpRange = rangeList.get(j);
                    Integer tmpValue = random.nextInt(tmpRange.getBig() - tmpRange.getSmall()) + tmpRange.getSmall();
                    Integer levelCountTotal;
                    if (j == ratioList.size() - 1) {
                        levelCountTotal = businessTotal - tmpSum;
                    } else {
                        levelCountTotal = (int) (ratioList.get(j) * businessTotal);
                        tmpSum += levelCountTotal;
                    }
                    for (int pos = 0; pos < levelCountTotal; ++pos) {
                        Integer personIndex = queue.get(values.get(pos + begin));
                        Business business = persons.get(personIndex).getBusinessAttribute().get(k + 1);
                        business.getLabelMap().put(labelName, tmpValue);
                        business.getLevelMap().put(labelName, labelList.get(j));
                        businessQueue.statisticBusinessLabel(k + 1, labelName, labelList.get(j), personIndex);
                    }
                    begin = tmpSum - 1;
                }
            }
        }
    }


    private void createSingleLabelAttribute() {
        Random random = new Random();

        for (int i = 0; i < singleNames.length; ++i) {
            //get ratio
            List<Double> ratios = singleLabelArg.getRatioMap().get(singleNames[i]);
            //get range
            List<NumberRange> ranges = singleLabelArg.getRangeMap().get(singleNames[i]);
            //get label
            List<String> labels = singleLabelArg.getLevelMap().get(singleNames[i]);
            //generate a random link
            List<Integer> link = new LinkedList<>();
            for (int j = 0; j < numberOfPerson; ++j) {
                link.add(j + 1);
            }
            for (int j = 0; j < ratios.size(); ++j) {
                //cal the number
                Integer number = (int) (numberOfPerson * ratios.get(j));
                //get the numberRange
                NumberRange range = ranges.get(j);
                //generate value
                List<Integer> generatedNumbers = CommonFunction.createListRandomValues(number, range.getSmall(), range.getBig() - 1);
                for (int k = 0; k < number; ++k) {
                    //find people and give the value
                    Integer pos = random.nextInt(link.size());
                    Integer peopleName = link.get(pos);
                    link.remove(pos.intValue());
                    persons.get(peopleName).getLabelMap().put(singleNames[i], generatedNumbers.get(k));
                    persons.get(peopleName).getLevelMap().put(singleNames[i], labels.get(j));
                    businessQueue.statisticLabel(singleNames[i], labels.get(j), peopleName);
                }
            }
        }
    }
}
